package service

import (
	"bytes"
	"encoding/binary"
	"fmt"
	log "github.com/sirupsen/logrus"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"os/exec"
	"strings"
	"unicode/utf16"
	"usbipproxy/common"
	"usbipproxy/domain/vo"
)

type DeviceWindowsService struct {
	cache DeviceCacheService
}

/*
wmic path Win32_PnPEntity where "DeviceID like '%VID_0000&PID_3825%'" get /format:list
E:\code\goproject\test\vidquery>wmic path Win32_PnPEntity where "DeviceID like '%VID_0000&PID_3825%'" get /format:list

Availability=
Caption=HID-compliant mouse
ClassGuid={4d36e96f-e325-11ce-bfc1-08002be10318}
CompatibleID=
ConfigManagerErrorCode=0
ConfigManagerUserConfig=FALSE
CreationClassName=Win32_PnPEntity
Description=HID-compliant mouse
DeviceID=HID\VID_0000&amp;PID_3825\7&amp;145C4D81&amp;0&amp;0000
ErrorCleared=
ErrorDescription=
HardwareID={"HID\VID_0000&amp;PID_3825&amp;REV_0100","HID\VID_0000&amp;PID_3825","HID_DEVICE_SYSTEM_MOUSE","HID_DEVICE_UP:0001_U:0002","HID_DEVICE"}
InstallDate=
LastErrorCode=
Manufacturer=Microsoft
Name=HID-compliant mouse
PNPClass=Mouse
PNPDeviceID=HID\VID_0000&amp;PID_3825\7&amp;145C4D81&amp;0&amp;0000
PowerManagementCapabilities=
PowerManagementSupported=
Present=TRUE
Service=mouhid
Status=OK
StatusInfo=
SystemCreationClassName=Win32_ComputerSystem
SystemName=ZXF

Availability=
Caption=USB 输入设备
ClassGuid={745a17a0-74d3-11d0-b6fe-00a0c90f57da}
CompatibleID={"USB\COMPAT_VID_0000&amp;Class_03&amp;SubClass_01&amp;Prot_02","USB\COMPAT_VID_0000&amp;Class_03&amp;SubClass_01","USB\COMPAT_VID_0000&amp;Class_03","USB\Class_03&amp;SubClass_01&amp;Prot_02","USB\Class_03&amp;SubClass_01","USB\Class_03"}
ConfigManagerErrorCode=0
ConfigManagerUserConfig=FALSE
CreationClassName=Win32_PnPEntity
Description=USB 输入设备
DeviceID=USB\VID_0000&amp;PID_3825\6&amp;32094969&amp;0&amp;2
ErrorCleared=
ErrorDescription=
HardwareID={"USB\VID_0000&amp;PID_3825&amp;REV_0100","USB\VID_0000&amp;PID_3825"}
InstallDate=
LastErrorCode=
Manufacturer=(标准系统设备)
Name=USB 输入设备
PNPClass=HIDClass
PNPDeviceID=USB\VID_0000&amp;PID_3825\6&amp;32094969&amp;0&amp;2
PowerManagementCapabilities=
PowerManagementSupported=
Present=TRUE
Service=HidUsb
Status=OK
StatusInfo=
SystemCreationClassName=Win32_ComputerSystem
SystemName=ZXF
*/
func (d *DeviceWindowsService) GetDeviceInfo(vid, pid string) []*vo.DeviceInfo {

	cacheInfo := d.cache.GetDeviceInfo(vid, pid)
	if len(cacheInfo) > 0 {
		return cacheInfo
	}

	cmds := []string{
		"wmic",
		"path",
		"Win32_PnPEntity",
		"where",
		fmt.Sprintf("DeviceID like '%%%%VID_%s&PID_%s%%%%'", vid, pid),
		"get",
		"/format:list",
	}

	// 执行命令
	cmd := exec.Command(cmds[0], cmds[1:]...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		log.Printf("执行命令失败: %v\n命令: %s\n输出: %s",
			err, strings.Join(cmds, " "), string(output))
		return nil
	}

	// 解析输出
	devices, err := parseWmicOutput(output)
	if err != nil {
		log.Printf("解析输出失败: %v\n原始输出:\n%s", err, string(output))
		return nil
	}

	log.Debugf("\nGetDeviceInfo:%v:%v\n%#v", vid, pid, devices)
	rets := make([]*vo.DeviceInfo, 0, len(devices))
	for _, item := range devices {
		tmpInfo := &vo.DeviceInfo{
			Vid:          vid,
			Pid:          pid,
			DeviceName:   item["Name"],
			DeviceDesc:   item["Description"],
			PnpClass:     item["PNPClass"],
			ClassGuid:    item["ClassGuid"],
			Manufacturer: item["Manufacturer"],
		}
		keys := []string{strings.ToLower(item["Name"]), strings.ToLower(item["Description"]), strings.ToLower(item["Caption"])}
		for _, key := range keys {
			if strings.Contains(key, "key") {
				continue
			}

			if d.cache.NeedUpanSkip(key) {
				continue
			}

			if strings.Contains(key, "storage") {
				tmpInfo.PnpClass = common.PnpClassMassStorage
				break
			}
		}
		rets = append(rets, tmpInfo)
	}

	d.cache.SetDeviceInfo(vid, pid, rets)
	return rets
}

func NewDeviceWindowsService(upanSkipWords string) DeviceService {
	impl := &DeviceWindowsService{
		cache: NewDeviceCacheServiceImpl(upanSkipWords),
	}

	return impl
}
func decodeUTF16(b []byte) (string, error) {
	// 检查 BOM (Byte Order Mark) 以确定字节序
	var bom uint16
	if len(b) >= 2 {
		bom = binary.LittleEndian.Uint16(b[:2])
	}

	// 根据 BOM 确定字节序
	var endian binary.ByteOrder = binary.LittleEndian
	if bom == 0xFFFE {
		// 大端序
		endian = binary.BigEndian
		b = b[2:] // 跳过 BOM
	} else if bom == 0xFEFF {
		// 小端序
		b = b[2:] // 跳过 BOM
	}

	// 将字节切片转换为 UTF-16 编码的码点
	if len(b)%2 != 0 {
		return "", fmt.Errorf("invalid UTF-16 length: %d bytes", len(b))
	}

	u16s := make([]uint16, 0, len(b)/2)
	for i := 0; i < len(b); i += 2 {
		u16s = append(u16s, endian.Uint16(b[i:i+2]))
	}

	// 将 UTF-16 转换为 UTF-8
	runes := utf16.Decode(u16s)
	var buf bytes.Buffer
	for _, r := range runes {
		buf.WriteRune(r)
	}
	return buf.String(), nil
}

// 解析 WMIC 输出为结构化的 map 切片
func parseWmicOutput(output []byte) ([]map[string]string, error) {
	// 使用可靠的 UTF-16LE 解码
	str, err := convertGBKToUTF8(output)
	if err != nil {
		return nil, fmt.Errorf("UTF-16 decoding failed: %w", err)
	}

	var results []map[string]string
	current := make(map[string]string)

	// 处理每一行输出
	lines := strings.Split(strings.ReplaceAll(string(str), "\r", ""), "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if line == "" {
			// 空行表示新记录开始
			if len(current) > 0 {
				results = append(results, current)
				current = make(map[string]string)
			}
			continue
		}

		// 分割键值对
		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			continue
		}

		key := strings.TrimSpace(parts[0])
		value := strings.TrimSpace(parts[1])

		// 合并多行值
		if prev, exists := current[key]; exists {
			current[key] = prev + "\n" + value
		} else {
			current[key] = value
		}
	}

	// 添加最后一条记录
	if len(current) > 0 {
		results = append(results, current)
	}

	return results, nil
}

func convertGBKToUTF8(gbkData []byte) ([]byte, error) {
	reader := transform.NewReader(bytes.NewReader(gbkData), simplifiedchinese.GBK.NewDecoder())
	return io.ReadAll(reader)
}
